require 'domain_exception.rb'

class User < ActiveRecord::Base
  has_one :profile
  has_many :identities

  EMAIL_FORMAT_PATTERN = /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
  
  validates_presence_of :username, :email,:password, :message => 'can not be empty'
  validates_format_of :email, :with => EMAIL_FORMAT_PATTERN,  :if => Proc.new { |user| !user.email.blank? }
  validates_uniqueness_of :username, :if => Proc.new { |user| !user.username.blank? }
  validates_uniqueness_of :email, :if => Proc.new { |user| !user.email.blank? }
  
  before_save do |user|
    salt = [Array.new(6){rand(256).chr}.join].pack("m").chomp
    user.password_salt, user.password_hash = salt, Digest::SHA1.hexdigest(user.password + salt)
  end
  
  def password=(pass)
    @password = pass
  end
  
  def password
    @password
  end
  
  def change_password(old_pwd, new_pwd)
    User.authenticate(username, old_pwd)
    self.password = new_pwd
    save
  end
  
  def public_identities
    self.identities.select{|identity| identity.public?}
  end
  
  def fetch_identity(id)
    identity = Identity.find(id)
    raise NoPermissionException.new("can't access other's identity") unless identity.user == self
    identity  
  end
  
  def self.authenticate(username, password)
    user = User.find(:first, :conditions => [' username = ?' , username])
    if user.blank? || Digest::SHA1.hexdigest(password + user.password_salt) != user.password_hash
      raise AuthenticationFailureException.new("Username or password is invalid")
    end
    return user
  end  

  def self.is_admin(id)
    User.find(id).username == "gigix"
  end

  def self.find_by_initial(initial)
    unless initial.blank?
      other_type_username_users = find(:all, :conditions => ['username like ?', initial + '%']) 
      chinese_glyph_username_users = find_by_sql ["select users.* from users, pinyin where pinyin.initial = ? and users.username like concat(pinyin.glyph, '%')", initial]
      users = chinese_glyph_username_users + other_type_username_users
    end  
  end  
end
